/**
 * 配置管理器
 * 负责管理插件的配置信息，包括服务器连接信息和同步设置
 * 
 * @author lihengtt <lihengsir@gmail.com>
 * @github https://github.com/lihengtt
 */

import * as vscode from 'vscode';
import * as fs from 'fs';
import * as path from 'path';

export interface ServerInfo {
    host: string;
    port: number;
    username: string;
    password?: string;  // 添加密码字段
    privateKeyPath?: string;
}

export interface RsyncConfig {
    serverInfo: ServerInfo;
    localPath: string;
    remotePath: string;
    excludeRules: string[];
    autoSync: boolean;
    syncDelay: number;
}

/**
 * 扩展的QuickPickItem接口
 */
interface ConfigQuickPickItem extends vscode.QuickPickItem {
    key: string;
}

export class ConfigManager {
    private static readonly CONFIG_FILE = '.rsync-deployment.json';
    private config: RsyncConfig | null = null;
    private workspaceRoot: string;

    /**
     * 构造函数
     */
    constructor(private _context: vscode.ExtensionContext) {
        this.workspaceRoot = vscode.workspace.workspaceFolders?.[0]?.uri.fsPath || '';
        this.loadConfig();
    }

    /**
     * 获取配置信息
     * @returns RsyncConfig | null
     */
    getConfig(): RsyncConfig | null {
        return this.config;
    }

    /**
     * 设置配置信息
     * @param config - 配置信息
     */
    async setConfig(config: RsyncConfig): Promise<void> {
        this.config = config;
        await this.saveConfig();
    }

    /**
     * 更新配置信息
     * @param updates - 要更新的配置项
     */
    async updateConfig(updates: Partial<RsyncConfig>): Promise<void> {
        if (this.config) {
            this.config = { ...this.config, ...updates };
            await this.saveConfig();
        }
    }

    /**
     * 检查配置是否有效
     * @returns boolean
     */
    isConfigValid(): boolean {
        if (!this.config) {
            return false;
        }

        const { serverInfo, localPath, remotePath } = this.config;
        
        return !!(serverInfo.host && 
                 serverInfo.port && 
                 serverInfo.username && 
                 localPath && 
                 remotePath);
    }

    /**
     * 获取配置文件路径
     * @returns string
     */
    private getConfigPath(): string {
        return path.join(this.workspaceRoot, ConfigManager.CONFIG_FILE);
    }

    /**
     * 加载配置文件
     */
    private loadConfig(): void {
        try {
            const configPath = this.getConfigPath();
            if (fs.existsSync(configPath)) {
                const configData = fs.readFileSync(configPath, 'utf8');
                this.config = JSON.parse(configData);
            }
        } catch (error) {
            console.error('加载配置文件失败:', error);
            this.config = null;
        }
    }

    /**
     * 保存配置文件
     */
    private async saveConfig(): Promise<void> {
        try {
            const configPath = this.getConfigPath();
            const configData = JSON.stringify(this.config, null, 2);
            fs.writeFileSync(configPath, configData, 'utf8');
            
            vscode.window.showInformationMessage('配置已保存');
        } catch (error) {
            console.error('保存配置文件失败:', error);
            vscode.window.showErrorMessage('保存配置失败: ' + error);
        }
    }

    /**
     * 显示配置对话框
     * @author lihengtt <lihengsir@gmail.com>
     */
    async showConfigDialog(): Promise<void> {
        const currentConfig = this.config || {
            serverInfo: {
                host: '',
                port: 22,
                username: '',
                privateKeyPath: ''
            },
            localPath: this.workspaceRoot,
            remotePath: '',
            excludeRules: [
                'node_modules/**',
                '.git/**',
                '.vscode/**',
                '*.log',
                '.DS_Store'
            ],
            autoSync: false,
            syncDelay: 1000
        };
        
        // 使用更好的配置界面
        await this.showImprovedConfigDialog(currentConfig);
    }
    

    
    /**
     * 显示改进的配置对话框
     * @param currentConfig - 当前配置
     * @author lihengtt <lihengsir@gmail.com>
     */
    private async showImprovedConfigDialog(currentConfig: RsyncConfig): Promise<void> {
        const configItems: ConfigQuickPickItem[] = [
            {
                label: '$(server) 服务器主机',
                description: currentConfig.serverInfo.host || '未设置',
                detail: '配置服务器地址，例如: example.com 或 192.168.1.100',
                key: 'host'
            },
            {
                label: '$(symbol-numeric) SSH端口',
                description: currentConfig.serverInfo.port.toString(),
                detail: '配置SSH连接端口，默认: 22',
                key: 'port'
            },
            {
                label: '$(person) 用户名',
                description: currentConfig.serverInfo.username || '未设置',
                detail: '配置SSH登录用户名，例如: root 或 ubuntu',
                key: 'username'
            },
            {
                label: '$(key) 认证方式',
                description: currentConfig.serverInfo.privateKeyPath ? '私钥认证' : '密码认证',
                detail: '选择SSH认证方式：私钥文件或密码',
                key: 'auth'
            },
            {
                label: '$(folder) 本地路径',
                description: currentConfig.localPath,
                detail: '配置本地项目路径',
                key: 'localPath'
            },
            {
                label: '$(cloud) 远程路径',
                description: currentConfig.remotePath || '未设置',
                detail: '配置远程服务器路径，例如: /var/www/html',
                key: 'remotePath'
            },
            {
                label: '$(exclude) 排除规则',
                description: `${currentConfig.excludeRules.length} 个规则`,
                detail: '配置同步时要排除的文件和目录',
                key: 'excludeRules'
            },
            {
                label: '$(sync) 自动同步',
                description: currentConfig.autoSync ? '已启用' : '已禁用',
                detail: '配置是否启用文件自动同步',
                key: 'autoSync'
            },
            {
                label: '$(clock) 同步延迟',
                description: `${currentConfig.syncDelay}ms`,
                detail: '配置文件变化后的同步延迟时间',
                key: 'syncDelay'
            },
            {
                label: '$(save) 保存配置',
                description: '保存当前配置',
                detail: '保存所有配置项到配置文件',
                key: 'save'
            }
        ];
        
        const quickPick = vscode.window.createQuickPick<ConfigQuickPickItem>();
        quickPick.title = 'Rsync 部署配置';
        quickPick.placeholder = '选择要配置的项目';
        quickPick.items = configItems;
        quickPick.canSelectMany = false;
        
        let tempConfig = { ...currentConfig };
        
        quickPick.onDidChangeSelection(async (items) => {
            if (items.length > 0) {
                const selectedItem = items[0];
                await this.handleConfigItem(selectedItem.key, tempConfig);
                
                // 更新显示的配置项
                quickPick.items = this.updateConfigItems(configItems, tempConfig);
            }
        });
        
        quickPick.onDidHide(() => {
            quickPick.dispose();
        });
        
        quickPick.show();
    }
    
    /**
     * 更新配置项显示
     * @param items - 配置项列表
     * @param config - 当前配置
     * @author lihengtt <lihengsir@gmail.com>
     */
    private updateConfigItems(items: ConfigQuickPickItem[], config: RsyncConfig): ConfigQuickPickItem[] {
        return items.map(item => {
            switch (item.key) {
                case 'host':
                    return { ...item, description: config.serverInfo.host || '未设置' };
                case 'port':
                    return { ...item, description: config.serverInfo.port.toString() };
                case 'username':
                    return { ...item, description: config.serverInfo.username || '未设置' };
                case 'auth':
                    return { ...item, description: config.serverInfo.privateKeyPath ? '私钥认证' : '密码认证' };
                case 'localPath':
                    return { ...item, description: config.localPath };
                case 'remotePath':
                    return { ...item, description: config.remotePath || '未设置' };
                case 'excludeRules':
                    return { ...item, description: `${config.excludeRules.length} 个规则` };
                case 'autoSync':
                    return { ...item, description: config.autoSync ? '已启用' : '已禁用' };
                case 'syncDelay':
                    return { ...item, description: `${config.syncDelay}ms` };
                default:
                    return item;
            }
        });
    }
    
    /**
     * 处理配置项
     * @param key - 配置项键
     * @param config - 配置对象
     * @author lihengtt <lihengsir@gmail.com>
     */
    private async handleConfigItem(key: string, config: RsyncConfig): Promise<void> {
        switch (key) {
            case 'host':
                const host = await vscode.window.showInputBox({
                    prompt: '请输入服务器主机地址',
                    value: config.serverInfo.host,
                    placeHolder: '例如: example.com 或 192.168.1.100'
                });
                if (host !== undefined) {
                    config.serverInfo.host = host;
                }
                break;
                
            case 'port':
                const portStr = await vscode.window.showInputBox({
                    prompt: '请输入SSH端口',
                    value: config.serverInfo.port.toString(),
                    placeHolder: '默认: 22'
                });
                if (portStr !== undefined) {
                    config.serverInfo.port = parseInt(portStr) || 22;
                }
                break;
                
            case 'username':
                const username = await vscode.window.showInputBox({
                    prompt: '请输入用户名',
                    value: config.serverInfo.username,
                    placeHolder: '例如: root 或 ubuntu'
                });
                if (username !== undefined) {
                    config.serverInfo.username = username;
                }
                break;
                
            case 'auth':
                const authOptions = ['私钥认证', '密码认证'];
                const authChoice = await vscode.window.showQuickPick(authOptions, {
                    placeHolder: '选择认证方式'
                });
                if (authChoice === '私钥认证') {
                    const privateKeyPath = await vscode.window.showInputBox({
                        prompt: '请输入私钥文件路径',
                        value: config.serverInfo.privateKeyPath || '',
                        placeHolder: '例如: ~/.ssh/id_rsa'
                    });
                    if (privateKeyPath !== undefined) {
                        config.serverInfo.privateKeyPath = privateKeyPath;
                        config.serverInfo.password = undefined;
                    }
                } else if (authChoice === '密码认证') {
                    const password = await vscode.window.showInputBox({
                        prompt: '请输入SSH密码',
                        placeHolder: '输入服务器登录密码',
                        password: true
                    });
                    if (password !== undefined) {
                        config.serverInfo.password = password;
                        config.serverInfo.privateKeyPath = undefined;
                    }
                }
                break;
                
            case 'localPath':
                const localPath = await vscode.window.showInputBox({
                    prompt: '请输入本地项目路径',
                    value: config.localPath,
                    placeHolder: '当前工作区路径'
                });
                if (localPath !== undefined) {
                    config.localPath = localPath;
                }
                break;
                
            case 'remotePath':
                const remotePath = await vscode.window.showInputBox({
                    prompt: '请输入远程项目路径',
                    value: config.remotePath,
                    placeHolder: '例如: /var/www/html'
                });
                if (remotePath !== undefined) {
                    config.remotePath = remotePath;
                }
                break;
                
            case 'excludeRules':
                const excludeRulesStr = await vscode.window.showInputBox({
                    prompt: '请输入排除规则（用逗号分隔）',
                    value: config.excludeRules.join(', '),
                    placeHolder: '例如: node_modules/**, .git/**, *.log'
                });
                if (excludeRulesStr !== undefined) {
                    config.excludeRules = excludeRulesStr.split(',').map(rule => rule.trim()).filter(rule => rule);
                }
                break;
                
            case 'autoSync':
                const autoSyncOptions = ['启用', '禁用'];
                const autoSyncChoice = await vscode.window.showQuickPick(autoSyncOptions, {
                    placeHolder: '选择自动同步状态'
                });
                if (autoSyncChoice !== undefined) {
                    config.autoSync = autoSyncChoice === '启用';
                }
                break;
                
            case 'syncDelay':
                const syncDelayStr = await vscode.window.showInputBox({
                    prompt: '请输入同步延迟时间（毫秒）',
                    value: config.syncDelay.toString(),
                    placeHolder: '默认: 1000'
                });
                if (syncDelayStr !== undefined) {
                    config.syncDelay = parseInt(syncDelayStr) || 1000;
                }
                break;
                
            case 'save':
                await this.setConfig(config);
                vscode.window.showInformationMessage('配置已保存成功！');
                break;
        }
    }
    
    /**
     * 显示原始配置对话框（保留作为备用）
     * @author lihengtt <lihengsir@gmail.com>
     */
    private async showLegacyConfigDialog(): Promise<void> {
        const currentConfig = this.config || {
            serverInfo: {
                host: '',
                port: 22,
                username: '',
                privateKeyPath: ''
            },
            localPath: this.workspaceRoot,
            remotePath: '',
            excludeRules: [
                'node_modules/**',
                '.git/**',
                '.vscode/**',
                '*.log',
                '.DS_Store'
            ],
            autoSync: false,
            syncDelay: 1000
        };

        // 服务器主机
        const host = await vscode.window.showInputBox({
            prompt: '请输入服务器主机地址',
            value: currentConfig.serverInfo.host,
            placeHolder: '例如: example.com 或 192.168.1.100'
        });
        if (host === undefined) return;

        // 服务器端口
        const portStr = await vscode.window.showInputBox({
            prompt: '请输入SSH端口',
            value: currentConfig.serverInfo.port.toString(),
            placeHolder: '默认: 22'
        });
        if (portStr === undefined) return;
        const port = parseInt(portStr) || 22;

        // 用户名
        const username = await vscode.window.showInputBox({
            prompt: '请输入用户名',
            value: currentConfig.serverInfo.username,
            placeHolder: '例如: root 或 ubuntu'
        });
        if (username === undefined) return;

        // 私钥路径（可选）
        const privateKeyPath = await vscode.window.showInputBox({
            prompt: '请输入私钥文件路径（可选，留空使用密码认证）',
            value: currentConfig.serverInfo.privateKeyPath || '',
            placeHolder: '例如: ~/.ssh/id_rsa'
        });
        if (privateKeyPath === undefined) return;

        // 如果没有私钥路径，则询问密码
        let password: string | undefined;
        if (!privateKeyPath || privateKeyPath.trim() === '') {
            password = await vscode.window.showInputBox({
                prompt: '请输入SSH密码',
                value: '', // 不显示当前密码
                placeHolder: '输入服务器登录密码',
                password: true  // 隐藏输入内容
            });
            if (password === undefined) return;
        }

        // 本地项目路径
        const localPath = await vscode.window.showInputBox({
            prompt: '请输入本地项目路径',
            value: currentConfig.localPath,
            placeHolder: '当前工作区路径'
        });
        if (localPath === undefined) return;

        // 远程项目路径
        const remotePath = await vscode.window.showInputBox({
            prompt: '请输入远程项目路径',
            value: currentConfig.remotePath,
            placeHolder: '例如: /var/www/html'
        });
        if (remotePath === undefined) return;

        // 排除规则
        const excludeRulesStr = await vscode.window.showInputBox({
            prompt: '请输入排除规则（用逗号分隔）',
            value: currentConfig.excludeRules.join(', '),
            placeHolder: '例如: node_modules/**, .git/**, *.log'
        });
        if (excludeRulesStr === undefined) return;
        const excludeRules = excludeRulesStr.split(',').map(rule => rule.trim()).filter(rule => rule);

        // 自动同步
        const autoSyncOptions = ['是', '否'];
        const autoSyncChoice = await vscode.window.showQuickPick(autoSyncOptions, {
            placeHolder: '是否启用自动同步？'
        });
        if (autoSyncChoice === undefined) return;
        const autoSync = autoSyncChoice === '是';

        // 同步延迟
        const syncDelayStr = await vscode.window.showInputBox({
            prompt: '请输入同步延迟时间（毫秒）',
            value: currentConfig.syncDelay.toString(),
            placeHolder: '默认: 1000'
        });
        if (syncDelayStr === undefined) return;
        const syncDelay = parseInt(syncDelayStr) || 1000;

        // 保存配置
        const newConfig: RsyncConfig = {
            serverInfo: {
                host,
                port,
                username,
                password: password || undefined,  // 添加密码字段
                privateKeyPath: privateKeyPath || undefined
            },
            localPath,
            remotePath,
            excludeRules,
            autoSync,
            syncDelay
        };

        await this.setConfig(newConfig);
    }

    /**
     * 获取工作区根路径
     * @returns string
     */
    getWorkspaceRoot(): string {
        return this.workspaceRoot;
    }

    /**
     * 检查rsync是否可用
     * @author lihengtt <lihengsir@gmail.com>
     * @returns Promise<boolean>
     */
    async checkRsyncAvailable(): Promise<boolean> {
        return new Promise((resolve) => {
            try {
                const { spawn } = require('child_process');
                
                // 添加stdio配置避免EBADF错误
                const rsync = spawn('rsync', ['--version'], {
                    stdio: ['ignore', 'pipe', 'pipe']
                });
                
                // 设置5秒超时
                const timeout = setTimeout(() => {
                    rsync.kill('SIGTERM');
                    resolve(false);
                }, 5000);
                
                rsync.on('close', (code: number) => {
                    clearTimeout(timeout);
                    resolve(code === 0);
                });
                
                rsync.on('error', (error: Error) => {
                    clearTimeout(timeout);
                    console.error('rsync检查失败:', error.message);
                    resolve(false);
                });
                
                // 处理stdout和stderr数据流
                if (rsync.stdout) {
                    rsync.stdout.on('data', (_data: Buffer) => {
                        // 忽略输出
                    });
                }
                
                if (rsync.stderr) {
                    rsync.stderr.on('data', (_data: Buffer) => {
                        // 忽略错误输出
                    });
                }
                
            } catch (error) {
                console.error('spawn rsync失败:', error);
                resolve(false);
            }
        });
    }

    /**
     * 获取自动同步状态
     * @returns boolean
     */
    getAutoSyncEnabled(): boolean {
        return this.config?.autoSync || false;
    }

    /**
     * 设置自动同步状态
     * @param enabled - 是否启用自动同步
     */
    async setAutoSyncEnabled(enabled: boolean): Promise<void> {
        if (this.config) {
            this.config.autoSync = enabled;
            await this.saveConfig();
        }
    }

    /**
     * 显示配置面板
     */
    showConfigurationPanel(): void {
        this.showConfigDialog();
    }
}